﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Jinjia.Approve.Entity.Entity.JJFlow;
using Jinjia.Approve.IRepository.JJFlow;
using Jinjia.Approve.IService.JJFlow;
using Jinjia.Approve.Model.Input.JJFlow;
using Jinjia.Approve.Model.VM.JJFlow;
using Jinjia.Core.Attribute;
using Jinjia.Core.BaseInfrastructure.BaseModel.BaseModel;
using Jinjia.Core.BaseInfrastructure.StorageModel.Model;
using Microsoft.AspNetCore.Http;

namespace Jinjia.Approve.Service.JJFlow
{
    public class JJFlowTemplateService : IJJFlowTemplateService
    {
        private readonly IFlowMappingRepository _flowMappingRepository;
        private readonly IFlowTemplateRepository _flowTemplateRepository;
        private readonly IFlowDesignRepository _flowDesignRepository;
        private readonly IFlowDesignHistoryRepository _flowDesignHistoryRepository;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IMapper _mapper;

        public JJFlowTemplateService(IFlowMappingRepository flowMappingRepository,
            IFlowTemplateRepository flowTemplateRepository,
            IFlowDesignRepository flowDesignRepository,
            IFlowDesignHistoryRepository flowDesignHistoryRepository,
            IHttpContextAccessor httpContextAccessor,
            IMapper mapper)
        {
            _flowMappingRepository = flowMappingRepository;
            _flowTemplateRepository = flowTemplateRepository;
            _flowDesignRepository = flowDesignRepository;
            _flowDesignHistoryRepository = flowDesignHistoryRepository;
            _httpContextAccessor = httpContextAccessor;
            _mapper = mapper;
        }


        public async Task<int> GetTemplateID(string modular_key)
        {
            var jjFlowMappingTbl = await _flowMappingRepository.GetByModularKey(modular_key);
            return jjFlowMappingTbl?.template_id ?? 0;
        }

        public async Task<bool> IsExistTemplate(int template_id)
        {
            var jjFlowTemplate = await _flowTemplateRepository.GetById(template_id);
            return jjFlowTemplate != null;
        }

        public async Task<JjFlowTemplateVM> GetTemplateById(int template_id)
        {
            var jjFlowTemplate = await _flowTemplateRepository.GetById(template_id);
            if (jjFlowTemplate != null)
            {
                var jjFlowTemplateVm = _mapper.Map<JjFlowTemplateVM>(jjFlowTemplate);
                return jjFlowTemplateVm;
            }

            return null;
        }

        public async Task<PageListSearchResultVM<JJTemplateViewModel>> GetTemplatePageList(JJTemplateSearchCondition searchCondition)
        {
            var pageListSearchResultVm = await _flowTemplateRepository.GetTemplatePageList(searchCondition, GetUserId());
            foreach (var item in pageListSearchResultVm.data_list)
            {
                if (JJTemplateDIC.IsRevokeDIC.ContainsKey(item.is_revoke))
                {
                    item.is_revoke_name = JJTemplateDIC.IsRevokeDIC[item.is_revoke];
                }
            }

            return pageListSearchResultVm;
        }

        public async Task<JJTemplateSignleViewModel> GetTemplateDetail(int id)
        {
            var result = await _flowTemplateRepository.GetTemplateDetail(id);
            if (result != null)
            {
                var templateList = await _flowMappingRepository.GetByTemplateID(id);
                result.modular = templateList.Select(t => new JJTemplateMappingEditViewModel() { id = t.Key, modular_name = t.Value }).ToList();
            }

            return result;
        }

        [UseTran]
        public virtual async Task DeleteTemplate(int id)
        {
            await _flowTemplateRepository.LogicalDelete(id, GetUserId());
            await _flowMappingRepository.ClearTemplateIDByTemplateID(id, GetUserId());
        }

        [UseTran]
        public virtual async Task<ResponseResult<string>> SaveTemplate(JJTemplateEditViewModel model)
        {
            var existTemplate = await _flowTemplateRepository.GetExistTemplateByName(model.template_name, model.id);
            if (existTemplate.Count > 0)
            {
                return new ResponseResult<string>()
                {
                    IsSuccess = false,
                    Message = "流程名称存在,不能重复添加"
                };
            }

            var existMappings = await _flowMappingRepository.GetMappingByIds(model.modular_id.Select(t => t.id).ToList());

            //系统不存在业务类型
            var noExistMapping = new List<string>();
            //其他流程所属业务类型
            var otherTemplateMapping = new List<string>();
            foreach (var item in model.modular_id)
            {
                if (existMappings.All(t => t.id != item.id))
                {
                    noExistMapping.Add(item.modular_name);
                }
                else
                {
                    var currentMapping = existMappings.First(t => t.id == item.id);
                    if (currentMapping.template_id != 0 && currentMapping.template_id != model.id)
                    {
                        otherTemplateMapping.Add(item.modular_name);
                    }
                }
            }

            if (noExistMapping.Count > 0)
            {
                return new ResponseResult<string>()
                {
                    IsSuccess = false,
                    Message = string.Join(",", noExistMapping) + "。业务类型不存在"
                };
            }

            if (otherTemplateMapping.Count > 0)
            {
                return new ResponseResult<string>()
                {
                    IsSuccess = false,
                    Message = string.Join(",", otherTemplateMapping) + "业务类型已存在审批流，请删除该流程后再添加"
                };
            }

            var flow_Template = new jj_flow_template();
            var oldMapping = new Dictionary<int, string>();

            if (model.id > 0)
            {
                flow_Template = await _flowTemplateRepository.GetById(model.id);
                if (flow_Template == null)
                {
                    return new ResponseResult<string>()
                    {
                        IsSuccess = false,
                        Message = "流程不存在"
                    };
                }

                oldMapping = await _flowMappingRepository.GetByTemplateID(model.id);

                flow_Template.template_name = model.template_name;
                flow_Template.remark = model.remark;
                flow_Template.is_revoke = model.is_revoke;
                flow_Template.is_auto_approve = model.is_auto_approve;
                flow_Template.update_user_id = GetUserId();
                flow_Template.is_submit_user_check = model.is_submit_user_check;
                flow_Template.page_id = model.page_id;
                flow_Template.page_parameter_key = model.page_parameter_key;
                flow_Template.detail_page_id = model.detail_page_id;
                flow_Template.detail_page_parameter_key = model.detail_page_parameter_key;
                flow_Template.business_table_name = model.business_table_name;
                flow_Template.logical_deleted_field=model.logical_deleted_field;
            }
            else
            {
                flow_Template.template_name = model.template_name;
                flow_Template.remark = model.remark;
                flow_Template.deleted = 0;
                flow_Template.is_revoke = model.is_revoke;
                flow_Template.is_auto_approve = model.is_auto_approve;
                flow_Template.create_user_id = flow_Template.update_user_id = GetUserId();
                flow_Template.create_time = flow_Template.update_time = DateTime.Now;
                flow_Template.is_submit_user_check = model.is_submit_user_check;
                flow_Template.page_id = model.page_id;
                flow_Template.page_parameter_key = model.page_parameter_key;
                flow_Template.detail_page_id = model.detail_page_id;
                flow_Template.detail_page_parameter_key = model.detail_page_parameter_key;
                flow_Template.business_table_name = model.business_table_name;
                flow_Template.logical_deleted_field = model.logical_deleted_field;
            }

            var clearMapping = oldMapping.Keys.ToList().Except(model.modular_id.Select(t => t.id).ToList()).ToList();
            var template_id = await _flowTemplateRepository.Save(flow_Template);

            if (clearMapping.Count > 0)
            {
                await _flowMappingRepository.UpdateMappingTemplateId(0, clearMapping, flow_Template.update_user_id);
            }

            await _flowMappingRepository.UpdateMappingTemplateId(template_id, model.modular_id.Select(t => t.id).ToList(), flow_Template.update_user_id);

            if (model.modular_id != null && model.modular_id.Count > 0)
            {
                //记录历史信息
                var designXml = await _flowDesignRepository.GetByTemplateId(model.id);
                if (designXml != null)
                {
                    var historyTbl = new jj_flow_design_history_tbl
                    {
                        history__xml = designXml.design_xml,
                        template_id = model.id,
                        modular_key = "",
                        create_user_id = GetUserId(),
                        create_time = DateTime.Now,
                        update_user_id = GetUserId(),
                        update_time = DateTime.Now,
                    };
                    await _flowDesignHistoryRepository.Save(historyTbl);
                }
            }

            return new ResponseResult<string>()
            {
                IsSuccess = true,
                Message = "保存成功"
            };
        }

        #region Private

        private int GetUserId()
        {
            var currentUserId = GetClaim("id");
            var result = int.TryParse(currentUserId, out int userId);
            return result ? userId : -100;
        }

        /// <summary>
        /// 获取授权用户身份信息
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private string GetClaim(string type)
        {
            return _httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(x => x.Type == type)?.Value;
        }

        #endregion
    }
}